"""
API Client for Desktop Application
桌面应用API客户端
"""

import asyncio
import aiohttp
import json
import logging
from typing import Optional, Dict, Any, List
from datetime import datetime, timedelta
from pathlib import Path

logger = logging.getLogger(__name__)


class APIError(Exception):
    """API错误异常"""
    
    def __init__(self, message: str, status_code: Optional[int] = None, error_code: Optional[str] = None):
        self.message = message
        self.status_code = status_code
        self.error_code = error_code
        super().__init__(message)


class AuthenticationError(APIError):
    """认证错误"""
    pass


class NetworkError(APIError):
    """网络错误"""
    pass


class ValidationError(APIError):
    """验证错误"""
    pass


class APIClient:
    """API客户端类"""
    
    def __init__(self, base_url: str, state_manager=None, timeout: int = 30):
        self.base_url = base_url.rstrip("/")
        self.state_manager = state_manager
        self.timeout = aiohttp.ClientTimeout(total=timeout)
        self.session: Optional[aiohttp.ClientSession] = None
        self._lock = asyncio.Lock()
        
        # 请求重试配置
        self.max_retries = 3
        self.retry_delay = 1.0
        
        logger.info(f"APIClient initialized with base URL: {base_url}")
    
    async def initialize(self) -> None:
        """初始化API客户端"""
        try:
            logger.info("Initializing API client")
            
            # 创建HTTP会话
            self.session = aiohttp.ClientSession(
                timeout=self.timeout,
                headers={
                    "Content-Type": "application/json",
                    "User-Agent": "MediaCreateDesktop/1.0.0",
                }
            )
            
            logger.info("API client initialized successfully")
            
        except Exception as e:
            logger.error(f"Failed to initialize API client: {e}")
            raise
    
    async def cleanup(self) -> None:
        """清理API客户端"""
        try:
            logger.info("Cleaning up API client")
            
            if self.session and not self.session.closed:
                await self.session.close()
                self.session = None
            
            logger.info("API client cleanup completed")
            
        except Exception as e:
            logger.error(f"Error during API client cleanup: {e}")
    
    async def _get_headers(self, include_auth: bool = True) -> Dict[str, str]:
        """获取请求头"""
        headers = {
            "Content-Type": "application/json",
            "Accept": "application/json",
        }
        
        if include_auth and self.state_manager:
            token = await self.state_manager.get_token()
            if token:
                headers["Authorization"] = f"Bearer {token}"
        
        return headers
    
    async def _make_request(
        self,
        method: str,
        endpoint: str,
        data: Optional[Dict[str, Any]] = None,
        params: Optional[Dict[str, Any]] = None,
        include_auth: bool = True,
        retry_count: int = 0
    ) -> Dict[str, Any]:
        """发送HTTP请求"""
        if not self.session:
            raise NetworkError("API client not initialized")
        
        url = f"{self.base_url}{endpoint}"
        headers = await self._get_headers(include_auth)
        
        try:
            logger.debug(f"Making {method} request to {url}")
            
            async with self.session.request(
                method=method,
                url=url,
                headers=headers,
                json=data,
                params=params
            ) as response:
                
                # 读取响应内容
                response_text = await response.text()
                
                try:
                    response_data = json.loads(response_text) if response_text else {}
                except json.JSONDecodeError:
                    response_data = {"message": response_text}
                
                logger.debug(f"Response: {response.status} - {response_data}")
                
                # 处理认证错误
                if response.status == 401:
                    if self.state_manager:
                        await self.state_manager.clear_token()
                    raise AuthenticationError(
                        response_data.get("error", {}).get("message", "认证失败"),
                        status_code=401
                    )
                
                # 处理客户端错误
                if 400 <= response.status < 500:
                    error_message = response_data.get("error", {}).get("message", "请求错误")
                    error_code = response_data.get("error", {}).get("code")
                    
                    if response.status == 422:
                        raise ValidationError(error_message, status_code=422, error_code=error_code)
                    else:
                        raise APIError(error_message, status_code=response.status, error_code=error_code)
                
                # 处理服务器错误
                if response.status >= 500:
                    if retry_count < self.max_retries:
                        logger.warning(f"Server error {response.status}, retrying in {self.retry_delay}s")
                        await asyncio.sleep(self.retry_delay)
                        return await self._make_request(
                            method, endpoint, data, params, include_auth, retry_count + 1
                        )
                    
                    raise NetworkError(
                        response_data.get("error", {}).get("message", "服务器错误"),
                        status_code=response.status
                    )
                
                # 检查响应格式
                if not response_data.get("success", True):
                    raise APIError(
                        response_data.get("error", {}).get("message", "操作失败"),
                        error_code=response_data.get("error", {}).get("code")
                    )
                
                return response_data.get("data", {})
                
        except aiohttp.ClientError as e:
            if retry_count < self.max_retries:
                logger.warning(f"Network error: {e}, retrying in {self.retry_delay}s")
                await asyncio.sleep(self.retry_delay)
                return await self._make_request(
                    method, endpoint, data, params, include_auth, retry_count + 1
                )
            
            raise NetworkError(f"网络错误: {e}")
        
        except asyncio.TimeoutError:
            if retry_count < self.max_retries:
                logger.warning(f"Request timeout, retrying in {self.retry_delay}s")
                await asyncio.sleep(self.retry_delay)
                return await self._make_request(
                    method, endpoint, data, params, include_auth, retry_count + 1
                )
            
            raise NetworkError("请求超时")
    
    # 认证相关API
    async def login(self, username: str, password: str) -> Dict[str, Any]:
        """用户登录"""
        data = {
            "username": username,
            "password": password
        }
        
        response_data = await self._make_request(
            "POST", "/auth/login", 
            data=data, 
            include_auth=False
        )
        
        # 保存认证令牌
        if self.state_manager and response_data.get("access_token"):
            await self.state_manager.save_token(response_data["access_token"])
        
        return response_data
    
    async def register(self, email: str, username: str, password: str, **kwargs) -> Dict[str, Any]:
        """用户注册"""
        data = {
            "email": email,
            "username": username,
            "password": password,
            **kwargs
        }
        
        return await self._make_request(
            "POST", "/auth/register", 
            data=data, 
            include_auth=False
        )
    
    async def logout(self) -> Dict[str, Any]:
        """用户登出"""
        response = await self._make_request("POST", "/auth/logout")
        
        # 清除本地令牌
        if self.state_manager:
            await self.state_manager.clear_token()
        
        return response
    
    async def get_current_user(self) -> Optional[Dict[str, Any]]:
        """获取当前用户信息"""
        try:
            return await self._make_request("GET", "/auth/profile")
        except AuthenticationError:
            return None
    
    async def update_profile(self, **kwargs) -> Dict[str, Any]:
        """更新用户资料"""
        return await self._make_request("PUT", "/auth/profile", data=kwargs)
    
    async def change_password(self, current_password: str, new_password: str) -> Dict[str, Any]:
        """修改密码"""
        data = {
            "current_password": current_password,
            "new_password": new_password
        }
        
        return await self._make_request("PUT", "/auth/password", data=data)
    
    # 内容管理相关API
    async def create_content(self, prompt: str, content_type: str, **kwargs) -> Dict[str, Any]:
        """创建内容"""
        data = {
            "prompt": prompt,
            "content_type": content_type,
            **kwargs
        }
        
        return await self._make_request("POST", "/content/create", data=data)
    
    async def get_content(self, content_id: str) -> Dict[str, Any]:
        """获取内容详情"""
        return await self._make_request("GET", f"/content/{content_id}")
    
    async def list_content(
        self, 
        page: int = 1, 
        page_size: int = 20, 
        **filters
    ) -> Dict[str, Any]:
        """获取内容列表"""
        params = {
            "page": page,
            "page_size": page_size,
            **filters
        }
        
        return await self._make_request("GET", "/content/", params=params)
    
    async def update_content(self, content_id: str, **kwargs) -> Dict[str, Any]:
        """更新内容"""
        return await self._make_request("PUT", f"/content/{content_id}", data=kwargs)
    
    async def delete_content(self, content_id: str) -> Dict[str, Any]:
        """删除内容"""
        return await self._make_request("DELETE", f"/content/{content_id}")
    
    async def download_content(self, content_id: str) -> Dict[str, Any]:
        """下载内容"""
        return await self._make_request("POST", f"/content/{content_id}/download")
    
    async def toggle_favorite(self, content_id: str) -> Dict[str, Any]:
        """切换收藏状态"""
        return await self._make_request("POST", f"/content/{content_id}/favorite")
    
    async def get_content_status(self, content_id: str) -> Dict[str, Any]:
        """获取内容状态"""
        return await self._make_request("GET", f"/content/{content_id}/status")
    
    # 文件夹管理相关API
    async def create_folder(self, name: str, **kwargs) -> Dict[str, Any]:
        """创建文件夹"""
        data = {"name": name, **kwargs}
        return await self._make_request("POST", "/folders/", data=data)
    
    async def get_folder_tree(self, **params) -> Dict[str, Any]:
        """获取文件夹树"""
        return await self._make_request("GET", "/folders/tree", params=params)
    
    async def get_folder(self, folder_id: str, **params) -> Dict[str, Any]:
        """获取文件夹详情"""
        return await self._make_request("GET", f"/folders/{folder_id}", params=params)
    
    async def update_folder(self, folder_id: str, **kwargs) -> Dict[str, Any]:
        """更新文件夹"""
        return await self._make_request("PUT", f"/folders/{folder_id}", data=kwargs)
    
    async def delete_folder(self, folder_id: str) -> Dict[str, Any]:
        """删除文件夹"""
        return await self._make_request("DELETE", f"/folders/{folder_id}")
    
    async def move_folder(self, folder_id: str, target_parent_id: Optional[str] = None) -> Dict[str, Any]:
        """移动文件夹"""
        params = {}
        if target_parent_id:
            params["target_parent_id"] = target_parent_id
        
        return await self._make_request("POST", f"/folders/{folder_id}/move", params=params)
    
    # 标签管理相关API
    async def create_tag(self, name: str, **kwargs) -> Dict[str, Any]:
        """创建标签"""
        data = {"name": name, **kwargs}
        return await self._make_request("POST", "/tags/", data=data)
    
    async def list_tags(self, **params) -> Dict[str, Any]:
        """获取标签列表"""
        return await self._make_request("GET", "/tags/", params=params)
    
    async def get_tag(self, tag_id: str, **params) -> Dict[str, Any]:
        """获取标签详情"""
        return await self._make_request("GET", f"/tags/{tag_id}", params=params)
    
    async def update_tag(self, tag_id: str, **kwargs) -> Dict[str, Any]:
        """更新标签"""
        return await self._make_request("PUT", f"/tags/{tag_id}", data=kwargs)
    
    async def delete_tag(self, tag_id: str) -> Dict[str, Any]:
        """删除标签"""
        return await self._make_request("DELETE", f"/tags/{tag_id}")
    
    async def add_content_tags(self, content_id: str, tag_ids: List[str]) -> Dict[str, Any]:
        """为内容添加标签"""
        data = {"tag_ids": tag_ids}
        return await self._make_request("POST", f"/tags/{content_id}/tags", data=data)
    
    async def remove_content_tags(self, content_id: str, tag_ids: List[str]) -> Dict[str, Any]:
        """从内容移除标签"""
        data = {"tag_ids": tag_ids}
        return await self._make_request("DELETE", f"/tags/{content_id}/tags", data=data)
    
    async def get_content_tags(self, content_id: str) -> Dict[str, Any]:
        """获取内容的标签"""
        return await self._make_request("GET", f"/tags/content/{content_id}")
    
    async def get_tag_suggestions(self, query: str, **params) -> Dict[str, Any]:
        """获取标签建议"""
        params["query"] = query
        return await self._make_request("GET", "/tags/suggestions", params=params)
    
    # 系统管理相关API（需要管理员权限）
    async def get_system_stats(self) -> Dict[str, Any]:
        """获取系统统计"""
        return await self._make_request("GET", "/admin/stats")
    
    async def get_system_health(self) -> Dict[str, Any]:
        """获取系统健康状态"""
        return await self._make_request("GET", "/admin/health")
    
    async def get_system_logs(self, **params) -> Dict[str, Any]:
        """获取系统日志"""
        return await self._make_request("GET", "/admin/logs", params=params)
    
    async def list_users(self, **params) -> Dict[str, Any]:
        """获取用户列表（管理员）"""
        return await self._make_request("GET", "/admin/users", params=params)
    
    async def update_user_role(self, user_id: str, role: str) -> Dict[str, Any]:
        """更新用户角色（管理员）"""
        params = {"role": role}
        return await self._make_request("PUT", f"/admin/users/{user_id}/role", params=params)
    
    async def update_user_status(self, user_id: str, status: str, reason: Optional[str] = None) -> Dict[str, Any]:
        """更新用户状态（管理员）"""
        params = {"status": status}
        if reason:
            params["reason"] = reason
        
        return await self._make_request("PUT", f"/admin/users/{user_id}/status", params=params)
    
    async def update_user_limits(self, user_id: str, **limits) -> Dict[str, Any]:
        """更新用户限制（管理员）"""
        return await self._make_request("PUT", f"/admin/users/{user_id}/limits", params=limits)
    
    async def get_content_statistics(self, **params) -> Dict[str, Any]:
        """获取内容统计"""
        return await self._make_request("GET", "/admin/content/stats", params=params)
    
    async def get_task_statistics(self) -> Dict[str, Any]:
        """获取任务统计"""
        return await self._make_request("GET", "/admin/tasks/stats")
    
    async def clear_system_logs(self, days_to_keep: int = 30) -> Dict[str, Any]:
        """清理系统日志（管理员）"""
        params = {"days_to_keep": days_to_keep}
        return await self._make_request("POST", "/admin/logs/clear", params=params)
    
    async def vacuum_database(self) -> Dict[str, Any]:
        """数据库维护（管理员）"""
        return await self._make_request("POST", "/admin/maintenance/vacuum")
    
    # 健康检查和连接测试
    async def health_check(self) -> bool:
        """健康检查"""
        try:
            await self._make_request("GET", "/health", include_auth=False)
            return True
        except Exception:
            return False
    
    async def test_connection(self) -> Dict[str, Any]:
        """测试连接"""
        try:
            start_time = asyncio.get_event_loop().time()
            
            # 尝试健康检查端点
            health_data = await self._make_request("GET", "/health", include_auth=False)
            
            end_time = asyncio.get_event_loop().time()
            response_time = end_time - start_time
            
            return {
                "connected": True,
                "response_time": response_time,
                "server_info": health_data,
                "timestamp": datetime.utcnow().isoformat()
            }
            
        except Exception as e:
            return {
                "connected": False,
                "error": str(e),
                "timestamp": datetime.utcnow().isoformat()
            }


# 导出
__all__ = ["APIClient", "APIError", "AuthenticationError", "NetworkError", "ValidationError"]